//
//  OATableConfig.m
//  OASDK_Works
//
//  Created by ChenJie on 3/29/20.
//  Copyright © 2020 Mist. All rights reserved.
//

#import "OATableConfig.h"
#import "OABase.h"
#import "OALog.h"

@interface OATableConfig ()

@property (nonatomic, strong) NSMutableArray<OASectionConfig *> *sections;
@property (nonatomic, strong) NSMutableDictionary<NSString *, OASectionConfig *> *sectionPool;

@end

@implementation OATableConfig

#pragma mark - Lifecycle methods

- (instancetype)init {
    self = [super init];
    if (self) {
    }
    return self;
}

#pragma mark - Public methods

/* add section */
- (OASectionConfig *)addSection:(OASectionConfig *)section {
    if (!section) {
        return nil;
    }
    
    __weak typeof(self) weakSelf = self;
    
    section.indexOfSection = ^NSInteger(OASectionConfig *section) {
        return [weakSelf.sections indexOfObject:section];
    };
    
    section.tableOfSection = ^OATableConfig *{
        return weakSelf;
    };
    
    [self.sections addObject:section];
    self.sectionPool[section.name] = section;
    
    return section;
}

- (OASectionConfig *)addSectionWithName:(NSString *)sectionName {
    OASectionConfig *section = [OASectionConfig sectionWithName:sectionName];
    return [self addSection:section];
}

/* get section */
- (OASectionConfig *)sectionAtIndex:(NSInteger)sectionIndex {
    if (sectionIndex >= self.sections.count) {
        return nil;
    }
    return self.sections[sectionIndex];
}

- (OASectionConfig *)sectionWithName:(NSString *)sectionName {
    return self.sectionPool[sectionName];
}

/* add cell for default section */
- (OACellConfig *)addCell:(OACellConfig *)cell {
    return [[self defaultSection] addCell:cell];
}

- (OACellConfig *)addCellWithType:(NSString *)cellType viewModel:(id)viewModel {
    return [[self defaultSection] addCellWithType:cellType viewModel:viewModel];
}

- (OACellConfig *)addCellWithType:(NSString *)cellType staticHeight:(CGFloat)staticHeight viewModel:(id)viewModel {
    return [[self defaultSection] addCellWithType:cellType staticHeight:staticHeight viewModel:viewModel];
}

- (OACellConfig *)addCellWithName:(NSString *)cellName type:(NSString *)cellType viewModel:(id)viewModel {
    return [[self defaultSection] addCellWithName:cellName type:cellType viewModel:viewModel];
}

- (OACellConfig *)addCellWithName:(NSString *)cellName
                             type:(NSString *)cellType
                     staticHeight:(CGFloat)staticHeight
                        viewModel:(id)viewModel{
    
    return [[self defaultSection] addCellWithName:cellName
                                             type:cellType
                                     staticHeight:staticHeight
                                        viewModel:viewModel];
}

/* get cell */
- (OACellConfig *)cellAtIndexPath:(NSIndexPath *)indexPath {
    OASectionConfig *sectionConfig = [self sectionAtIndex:indexPath.section];
    return [sectionConfig cellAtIndex:indexPath.row];
}

- (OACellConfig *)cellWithSectionName:(NSString *)sectionName cellName:(NSString *)cellName {
    OASectionConfig *sectionConfig = [self sectionWithName:sectionName];
    return [sectionConfig cellWithName:cellName];
}

/* get cell of default section */
- (OACellConfig *)cellAtIndex:(NSInteger)cellIndex {
    return [[self defaultSection] cellAtIndex:cellIndex];
}

- (OACellConfig *)cellWithName:(NSString *)cellName {
    return [[self defaultSection] cellWithName:cellName];
}

/* get cell viewModel */
- (id<OACellViewModelProtocol>)viewModelAtIndexPath:(NSIndexPath *)indexPath {
    OASectionConfig *sectionConfig = [self sectionAtIndex:indexPath.section];
    return [sectionConfig viewModelAtIndex:indexPath.row];
}

- (id<OACellViewModelProtocol>)viewModelWithSectionName:(NSString *)sectionName cellName:(NSString *)cellName {
    OASectionConfig *sectionConfig = [self sectionWithName:sectionName];
    return [sectionConfig viewModelWithName:cellName];
}

/* get cell viewModel of default section */
- (id<OACellViewModelProtocol>)viewModelAtIndex:(NSInteger)cellIndex {
    return [[self defaultSection] viewModelAtIndex:cellIndex];
}

- (id<OACellViewModelProtocol>)viewModelWithName:(NSString *)cellName {
    return [[self defaultSection] viewModelWithName:cellName];
}

/*  */
- (OASectionConfig *)sectionOfCell:(OACellConfig *)cell {
    return [self sectionAtIndex:cell.indexPath.section];
}

/* delete section */
- (void)deleteSectionAtIndex:(NSInteger)sectionIndex {
    OASectionConfig *section = [self sectionAtIndex:sectionIndex];
    
    [self.sections removeObject:section];
    [self.sectionPool removeObjectForKey:section.name];
}

- (void)deleteSectionWithName:(NSString *)sectionName {
    OASectionConfig *section = [self sectionWithName:sectionName];
    
    [self.sections removeObject:section];
    [self.sectionPool removeObjectForKey:sectionName];
}

/* delete cell */
- (void)removeAllCells {
    [self.sections removeAllObjects];
    [self.sectionPool removeAllObjects];
}

- (void)deleteCellAtIndexPath:(NSIndexPath *)indexPath {
    OASectionConfig *section = [self sectionAtIndex:indexPath.section];
    [section deleteCellAtIndex:indexPath.row];
}

- (void)deleteCellWithSectionName:(NSString *)sectionName cellName:(NSString *)cellName {
    OASectionConfig *section = [self sectionWithName:sectionName];
    [section deleteCellWithName:cellName];
}

- (void)deleteCell:(OACellConfig *)cell {
    OASectionConfig *section = [self sectionOfCell:cell];
    [section deleteCell:cell];
}

/* delete cell from default section */
- (void)deleteCellAtIndex:(NSInteger)cellIndex {
    [[self defaultSection] deleteCellAtIndex:cellIndex];
}

- (void)deleteCellWithName:(NSString *)cellName {
    [[self defaultSection] deleteCellWithName:cellName];
}

/* update cell */
- (void)updateCellAtIndexPath:(NSIndexPath *)indexPath {
    [self updateCellAtIndexPath:indexPath withAnimation:UITableViewRowAnimationNone];
}

- (void)updateCellAtIndexPath:(NSIndexPath *)indexPath withAnimation:(UITableViewRowAnimation)animation {
    [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:animation];
}

/* update section */
- (void)updateSection:(OASectionConfig *)section {
    [self updateSection:section withAnimation:UITableViewRowAnimationNone];
}

- (void)updateSection:(OASectionConfig *)section withAnimation:(UITableViewRowAnimation)animation {
    NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:section.sectionIndex];
    [self.tableView reloadSections:indexSet withRowAnimation:animation];
}

#pragma mark - Delegate methods

/* UITableViewDataSource */
- (NSInteger)numberOfSectionsInTableView {
    return self.sections.count;
}

- (NSInteger)numberOfRowsInSection:(NSInteger)section {
    OASectionConfig *sectionConfig = [self sectionConfigAtIndex:section];
    return [sectionConfig numberOfRowsInSection];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    OASectionConfig *sectionConfig = [self sectionConfigAtIndex:indexPath.section];
    return [sectionConfig tableView:tableView cellForRowAtIndex:indexPath.row];
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    OASectionConfig *sectionConfig = [self sectionConfigAtIndex:section];
    return sectionConfig.headerTitle;
}

- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
    OASectionConfig *sectionConfig = [self sectionConfigAtIndex:section];
    return sectionConfig.footerTitle;
}

/* UITableViewDelegate */
- (CGFloat)heightForRowWithCellWidth:(CGFloat)cellWidth indexPath:(NSIndexPath *)indexPath {
    OASectionConfig *sectionConfig = [self sectionConfigAtIndex:indexPath.section];
    return [sectionConfig heightForRowWithCellWidth:cellWidth cellIndex:indexPath.row];
}

- (void)didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    OASectionConfig *sectionConfig = [self sectionConfigAtIndex:indexPath.section];
    [sectionConfig didSelectRowAtIndex:indexPath.row];
}

- (CGFloat)heightForHeaderInSection:(NSInteger)section {
    OASectionConfig *sectionConfig = [self sectionConfigAtIndex:section];
    return sectionConfig.headerHeight;
}

- (CGFloat)heightForFooterInSection:(NSInteger)section {
    OASectionConfig *sectionConfig = [self sectionConfigAtIndex:section];
    return sectionConfig.footerHeight;
}

#pragma mark - Private methods

- (OASectionConfig *)sectionConfigAtIndex:(NSInteger)sectionIndex {
    if (self.sections.count <= sectionIndex) {
        return nil;
    }
    return self.sections[sectionIndex];
}

- (OASectionConfig *)defaultSection {
    OASectionConfig *sectionConfig = [self sectionConfigAtIndex:0];
    if (!sectionConfig) {
        sectionConfig = [OASectionConfig sectionWithName:nil];
        [self addSection:sectionConfig];
    }
    return sectionConfig;
}

#pragma mark - Delegate methods



#pragma mark - Setter



#pragma mark - Getter

- (NSMutableArray<OASectionConfig *> *)sections {
    if (!_sections) {
        _sections = [NSMutableArray array];
    }
    return _sections;
}

- (NSMutableDictionary<NSString *,OASectionConfig *> *)sectionPool {
    if (!_sectionPool) {
        _sectionPool = [NSMutableDictionary dictionary];
    }
    return _sectionPool;
}

#pragma mark - Memory management methods

- (void)dealloc {
    OALogFunction
}

@end
